package ua.kiev.tosik.price.modules.clients;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.validator.EmailValidator;
import org.apache.log4j.Logger;
import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.error.ErrorInfo;
import ua.kiev.tosik.price.models.Clients;
import ua.kiev.tosik.price.modules.clients.conf.ModuleConfig;
import ua.kiev.tosik.price.modules.clients.database.DataDeleteWorker;
import ua.kiev.tosik.price.modules.clients.database.DataSaveWorker;
import ua.kiev.tosik.price.modules.clients.database.DataUpdateWorker;
import ua.kiev.tosik.price.modules.clients.gui.EditorDialog;
import ua.kiev.tosik.price.modules.clients.gui.MainPanel;
import ua.kiev.tosik.price.modules.clients.gui.prices.PricesDialog;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class RecordEditor implements PropertyChangeListener {

	private static Logger logger = Logger.getLogger("ua.kiev.tosik.price.modules.clients");
	private EditorDialog dialog;
	private Clients client;
	private int rowIndex = -1;
	private ActionListener saveRecordAction;
	private ActionListener updateRecordAction;
	private ActionListener deleteRecordAction;
	private ActionListener pricesRecordAction;
	private ModuleConfig config;
	private PricesDialog pricesDialog;

	public RecordEditor() {
		logger.debug("Initialize Record Editor controller");
		dialog = EditorDialog.getInstance();
		config = ModuleConfig.getInstance();
		saveRecordAction = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				save();
			}
		};
		updateRecordAction = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				update();
			}
		};
		deleteRecordAction = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				delete();
			}
		};
		pricesRecordAction = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				openPricesDialog();
			}
		};
	}

	private void openPricesDialog() {
		logger.debug("Try to open Prices dialog");
		if ( pricesDialog == null ) {
			pricesDialog = PricesDialog.getInstance();
			pricesDialog.setClients(client);
		}
		SwingUtilities.invokeLater( new Runnable() {
			@Override
			public void run() {
				pricesDialog.open();
			}
		});
	}

	public void editRecord() {
		logger.debug("Open Record Editor for [edit] action");
		dialog.showEditButtons(true);
		dialog.setSaveButtonAction(updateRecordAction);
		dialog.setDeleteButtonAction(deleteRecordAction);
		dialog.setPricesButtonAction(pricesRecordAction);
		dialog.setFormData(client);
		dialog.open();
	}

	public void editRecord(Clients client) {
		this.client = client;
		editRecord();
	}

	public void createRecord() {
		logger.debug("Open Record Editor for [create_new] action");
		dialog.showEditButtons(false);
		dialog.setSaveButtonAction(saveRecordAction);
		dialog.clearForm();
		dialog.open();
	}

	public Clients getClient() {
		return client;
	}

	public void setClient(Clients client) {
		this.client = client;
	}

	public int getRowIndex() {
		return rowIndex;
	}

	public void setRowIndex(int rowIndex) {
		this.rowIndex = rowIndex;
	}

	/**
	 * For create record
	 */
	public void save() {
		Clients newClient = dialog.getFormData();
		if ( checkRecord(newClient) ) {
			dialog.enableForm(false);
			DataSaveWorker saveWorker = new DataSaveWorker();
			saveWorker.setClient(newClient);
			saveWorker.addPropertyChangeListener(this);
			saveWorker.execute();
		}
	}

	public boolean checkRecord(Clients client) {
		String title = config.get("clients.editor.message.error");
		if ( StringUtils.defaultString(client.getName()).equals("") ) {
			String message = config.get("clients.editor.message.name.isEmpty");
			String details = config.get("clients.editor.message.name.isEmptyLong");
			showMessageDialog(title, message, details);
			return false;
		}
		String email = StringUtils.defaultString(client.getEmail());
		if ( !email.equals("") && !EmailValidator.getInstance().isValid(email) ) {
			String message = config.get("clients.editor.message.email.incorrect");
			String details = config.get("clients.editor.message.email.incorrectLong");
			showMessageDialog(title, message, details);
			return false;
		}
		return true;
	}

	public void update() {
		Clients newClient = dialog.getFormData();
		if ( checkRecord(newClient) ) {
			dialog.enableForm(false);
			newClient.setId(client.getId());
			DataUpdateWorker updateWorker = new DataUpdateWorker();
			updateWorker.setClient(newClient);
			updateWorker.addPropertyChangeListener(this);
			updateWorker.execute();
		}
	}

	public void updateClientValue(Clients newClient) {
		setClient(newClient);
		MainPanel.getInstance().getTable().getModel().updateRow(getRowIndex(), newClient);
	}

	private void delete() {
		if ( rowIndex < 0 || client == null ) {
			return;
		}
		int res = JOptionPane.NO_OPTION;
		try {
			res = JOptionPane.showConfirmDialog(
				dialog.getDialog(),
				config.get("clients.editor.delete") + "?",
				config.get("clients.editor.delete") + "?",
				JOptionPane.YES_NO_OPTION,
				JOptionPane.PLAIN_MESSAGE,
				new ImageIcon(config.get("clients.editor.delete.icon"))
			);
		} catch (Exception e) {
			logger.warn(e.getLocalizedMessage());
		}
		if (res == JOptionPane.YES_OPTION) {
			DataDeleteWorker deleteWorker = new DataDeleteWorker();
			deleteWorker.setClient(client);
			deleteWorker.addPropertyChangeListener(this);
			deleteWorker.execute();
		}
	}

	private void showMessageDialog(String title, String message, String details) {
		ErrorInfo errorInfo = new ErrorInfo(title, message, details, "messageDialog", null, null, null);
		JXErrorPane.showDialog(dialog.getDialog(), errorInfo);
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if ( evt.getPropertyName().equals("SAVE_ERROR") ) {
			Exception e = (Exception)evt.getNewValue();
			String title = config.get("clients.editor.message.error");
			String message = e.getLocalizedMessage();
			showMessageDialog(title, message, message);
		}
		if ( evt.getPropertyName().equals("SAVE_OK") ) {
			dialog.enableForm(true);
			dialog.close();
		}
		if ( evt.getPropertyName().equals("UPDATE_OK") ) {
			Clients newClient = (Clients)evt.getNewValue();
			updateClientValue(newClient);
			dialog.enableForm(true);
		}
		if ( evt.getPropertyName().equals("DELETE_OK") ) {
			dialog.enableForm(true);
			setClient(null);
			MainPanel.getInstance().getTable().getModel().removeRow(getRowIndex());
			dialog.close();
		}
	}
}
